package cn.hznc.controller.service.toolAnalyze;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hznc.controller.service.schedule.ToolScheduleService;
import cn.hznc.controller.service.toollife.ToolLieService;
import cn.hznc.domain.entity.*;
import cn.hznc.domain.request.life.ToolUsageReportReq;
import cn.hznc.domain.request.schedule.ToolDemandPredictionReq;
import cn.hznc.domain.request.toolAnalyze.AssemblyRetrievalReq;
import cn.hznc.exception.ToolScheduleException;
import cn.hznc.utils.CommonUtil;
import cn.hznc.mapper.ToolForkInfoMapper;
import cn.hznc.mapper.ToolPartMapper;
import cn.hznc.repository.MachineToolTaskRespository;
import cn.hznc.repository.OrderRespository;
import cn.hznc.vo.OrderForecastReportExport;
import cn.hznc.vo.ToolDemandPredictionVo;
import cn.hznc.vo.ToolForkCountVo;
import cn.hznc.vo.ToolUsageReportExport;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ToolDemandForecastReportService {
    @Resource
    private ToolScheduleService toolScheduleService;

    @Resource
    private MachineToolTaskRespository machineToolTaskRespository;

    @Resource
    private OrderRespository orderRespository;
    @Resource
    private ToolPartMapper toolPartMapper;
    @Resource
    private ToolForkInfoMapper toolForkInfoMapper;

    @Resource
    private ToolLieService toolLieService;

    public Map<String,Object> queryToolDemandForecastReport(AssemblyRetrievalReq assemblyRetrievalReq) throws ToolScheduleException {
        LambdaQueryWrapper<ToolForkInfoEntity> lambdaQueryWrapper8 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper8.ne(ToolForkInfoEntity::getIdnr,"");
        lambdaQueryWrapper8.ne(ToolForkInfoEntity::getPrice,"");
        List<ToolForkInfoEntity> toolForkInfoEntityList2 = toolForkInfoMapper.selectList(lambdaQueryWrapper8);
        Map<String,List<ToolForkInfoEntity>> listMap = toolForkInfoEntityList2.stream().collect(Collectors.groupingBy(ToolForkInfoEntity::getIdnr));
        LambdaQueryWrapper<ToolPartEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ToolPartEntity::getToolNo,"");
        queryWrapper.ne(ToolPartEntity::getInventoryLocationId,"");
        List<ToolPartEntity> toolPartEntityList = toolPartMapper.selectList(queryWrapper);
        Map<String,List<ToolPartEntity>> stringListMap = toolPartEntityList.stream().collect(Collectors.groupingBy(ToolPartEntity::getToolNo));
        ToolDemandPredictionReq toolDemandPredictionReq = new ToolDemandPredictionReq();
        Map<String,Object> map1 = new HashMap<>();
        List<String>  taskIds = new ArrayList<>();
        taskIds.add(assemblyRetrievalReq.getTaskId());
        toolDemandPredictionReq.setTaskIds(taskIds);
        toolDemandPredictionReq.setPageNum(assemblyRetrievalReq.getPageNo());
        toolDemandPredictionReq.setPageSize(assemblyRetrievalReq.getPageSize());
        toolDemandPredictionReq.setFlag(assemblyRetrievalReq.getFlag());
        if (ObjectUtils.isNotEmpty(assemblyRetrievalReq.getId())){
            toolDemandPredictionReq.setId(assemblyRetrievalReq.getId());
        }
        Object orderEntities = toolScheduleService.getToolDemandPredictionListReload1(toolDemandPredictionReq);
//        toolDemandPredictionReq.setPageNum(toolDemandForecastReportReq.getPageNo());
//        toolDemandPredictionReq.setPageSize(toolDemandForecastReportReq.getPageSize());
//        toolDemandPredictionReq.setStartTime(toolDemandForecastReportReq.getStartTime());
//        toolDemandPredictionReq.setEndTime(toolDemandForecastReportReq.getEndTime());
//        Object orderEntities = toolScheduleService.getToolDemandPredictionList(toolDemandPredictionReq);
        Map<String,Object> map = JSONObject.parseObject(JSON.toJSONString(orderEntities));
        List<OrderEntity> orderEntityList = changeList(map.get("orderList"), OrderEntity.class);
        List<ToolDemandPredictionVo> toolDemandPredictionVoList = changeList(map.get("toolList"), ToolDemandPredictionVo.class);
        List<ToolDemandPredictionVo> allToolDemandPredictionVoList = changeList(map.get("allToolList"), ToolDemandPredictionVo.class);
        ToolDemandForecastReportProductEntity toolDemandForecastReportProductEntity = new ToolDemandForecastReportProductEntity();
        toolDemandForecastReportProductEntity.setTaskId(assemblyRetrievalReq.getTaskId());
        toolDemandForecastReportProductEntity.setProductName(orderEntityList.get(0).getProductionName());
        toolDemandForecastReportProductEntity.setProductType(orderEntityList.get(0).getProductionNum());
        toolDemandForecastReportProductEntity.setPartno(orderEntityList.get(0).getMaterialNo());
        toolDemandForecastReportProductEntity.setPlanNum(orderEntityList.get(0).getPlanNumber());
        List<String> machineList = new ArrayList<>();
        List<ToolDemandForecastReportToolEntity> toolDemandForecastReportToolEntityList = new ArrayList<>();
        List<BigDecimal> bigDecimalList = new ArrayList<>();
        List<Double> doubleList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(allToolDemandPredictionVoList)){
            allToolDemandPredictionVoList.forEach(toolDemandPredictionVo -> {
                if (!machineList.contains(toolDemandPredictionVo.getMachineToolName())){
                    machineList.add(toolDemandPredictionVo.getMachineToolName());
                }
//                toolDemandPredictionVo.get
                ToolDemandForecastReportToolEntity toolDemandForecastReportToolEntity = new ToolDemandForecastReportToolEntity();
                toolDemandForecastReportToolEntity.setToolNo(toolDemandPredictionVo.getToolCode());
                toolDemandForecastReportToolEntity.setHiltType(toolDemandPredictionVo.getShankModel());
                toolDemandForecastReportToolEntity.setBladeType(toolDemandPredictionVo.getToolModel());
                toolDemandForecastReportToolEntity.setPredictionNum(toolDemandPredictionVo.getPredictionNumber());
                toolDemandForecastReportToolEntity.setPredictionTime(toolDemandPredictionVo.getSingleTime());
                if (CollectionUtil.isNotEmpty(stringListMap.get(toolDemandPredictionVo.getToolCode()))){
                    toolDemandForecastReportToolEntity.setLocationNum(stringListMap.get(toolDemandPredictionVo.getToolCode()).size());
                }
                if (CollectionUtil.isNotEmpty(stringListMap.get(toolDemandPredictionVo.getToolCode()))){
                    toolDemandForecastReportToolEntity.setInventoryNum(stringListMap.get(toolDemandPredictionVo.getToolCode()).size());
                    if (StringUtils.isNotEmpty(stringListMap.get(toolDemandPredictionVo.getToolCode()).get(0).getLife())){
                        //toolDemandForecastReportToolEntity.setLife(stringListMap.get(toolDemandPredictionVo.getToolCode()).get(0).getLife());
                        toolDemandForecastReportToolEntity.setLife(toolScheduleService.getDefaultLife(toolDemandPredictionVo.getToolCode())+"");

                    }else {
                        //toolDemandForecastReportToolEntity.setLife(stringListMap.get(toolDemandPredictionVo.getToolCode()).get(0).getLife());
                        toolDemandForecastReportToolEntity.setLife(toolScheduleService.getDefaultLife(toolDemandPredictionVo.getToolCode())+"");
                    }
                }
//                LambdaQueryWrapper<ToolForkInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
////                lambdaQueryWrapper.eq(ToolForkInfoEntity::getIdnr,toolDemandPredictionVo.getShankModel());
////                lambdaQueryWrapper.ne(ToolForkInfoEntity::getPrice,"");
////                List<ToolForkInfoEntity> toolForkInfoEntityList1 = toolForkInfoMapper.selectList(lambdaQueryWrapper);
////                if (CollectionUtil.isNotEmpty(toolForkInfoEntityList1)){
////                    doubleList.add(toolForkInfoEntityList1.get(0).getPrice()*toolDemandPredictionVo.getPredictionNumber());
////                }
//                lambdaQueryWrapper.eq(ToolForkInfoEntity::getIdnr,toolDemandPredictionVo.getToolModel());
//                lambdaQueryWrapper.ne(ToolForkInfoEntity::getPrice,"");
//                List<ToolForkInfoEntity> toolForkInfoEntityList2 = toolForkInfoMapper.selectList(lambdaQueryWrapper);
                if (CollectionUtil.isNotEmpty(listMap.get(toolDemandPredictionVo.getToolModel()))){
//                    doubleList.add(toolForkInfoEntityList2.get(0).getPrice()*toolDemandPredictionVo.getPredictionNumber());
                    QueryWrapper<ToolForkInfoEntity> toolForkWrapper = new QueryWrapper<>();
                    toolForkWrapper.eq("idnr" , toolDemandPredictionVo.getToolModel());
                    List<ToolForkInfoEntity> toolForkInfoEntities = toolForkInfoMapper.selectList(toolForkWrapper);
                    List<String> partnos = toolForkInfoEntities
                            .stream()
                            .map(ToolForkInfoEntity::getPartno)
                            .collect(Collectors.toList());
                    if(CollectionUtil.isNotEmpty(partnos)){
                        //获取物料编码以及对应额定寿命
                        ToolForkCountVo toolForkCountVo = toolScheduleService.getDefaultLifeReload(toolDemandPredictionVo.getToolModel() , partnos);
                        //判断物料编码是否存在
                        Double price = 0.0;
                        if(ObjectUtil.isNotNull(toolForkCountVo)){
                            List<ToolForkCountVo> toolForkCountVos = new ArrayList<>();
                            if(ObjectUtil.isNull(toolForkCountVo.getPartno())){
                                //物料编码为空
                                toolForkInfoEntities.forEach(toolForkInfoEntity -> {
                                    if(ObjectUtil.isNotNull(toolForkInfoEntity.getPrice()) && toolForkInfoEntity.getPrice() - 0.11 >0){
                                        ToolForkCountVo priceToolForkCountVo = new ToolForkCountVo();
                                        priceToolForkCountVo.setPartno(toolForkInfoEntity.getPartno());
                                        priceToolForkCountVo.setPrice(toolForkInfoEntity.getPrice());
                                        toolForkCountVos.add(priceToolForkCountVo);
                                    }
                                });
                                if(CollectionUtil.isNotEmpty(toolForkCountVos)){
                                    //按价格排序后选择单件最大的进行计算
                                    List<ToolForkCountVo> sortByPrice = toolForkCountVos
                                            .stream()
                                            .sorted(Comparator.comparing(ToolForkCountVo::getPrice))
                                            .collect(Collectors.toList());
                                    toolForkCountVo.setPrice(sortByPrice.get(sortByPrice.size()-1).getPrice());
                                }
                            }else {
                                //物料编码不为空，按物料编码查询金额
                                toolForkInfoEntities.stream().forEach(toolForkInfoEntity -> {
                                    if(ObjectUtil.isNotNull(toolForkInfoEntity.getPrice()) && Objects.equals(toolForkInfoEntity.getPartno(), toolForkCountVo.getPartno())){
                                        toolForkCountVo.setPrice(toolForkInfoEntity.getPrice());
                                    }
                                });
                            }
                        }
                        if(ObjectUtil.isNotNull(toolForkCountVo)){
                            Double life = toolForkCountVo.getLife();
                            BigDecimal result = toolDemandPredictionVo.getSingleTime().divide(new BigDecimal(life) , 2 , BigDecimal.ROUND_HALF_UP);
//                            toolDemandForecastReportToolEntity.setPrice(listMap.get(toolDemandPredictionVo.getToolModel()).get(0).getPrice()*result.doubleValue());
//                            toolDemandForecastReportToolEntity.setUnitPrice(listMap.get(toolDemandPredictionVo.getToolModel()).get(0).getPrice());
                            toolDemandForecastReportToolEntity.setPartno(toolForkCountVo.getPartno());
                            toolDemandForecastReportToolEntity.setLife(toolForkCountVo.getLife().toString());
                            toolDemandForecastReportToolEntity.setPrice(toolForkCountVo.getPrice()*result.doubleValue());
                            toolDemandForecastReportToolEntity.setUnitPrice(toolForkCountVo.getPrice());
                        }
                    }
                }
                if(StringUtils.isBlank(toolDemandForecastReportToolEntity.getLife())){
                    toolDemandForecastReportToolEntity.setLife(toolScheduleService.getDefaultLife(toolDemandPredictionVo.getToolCode())+"");
                }
                toolDemandForecastReportToolEntityList.add(toolDemandForecastReportToolEntity);
            });
        }

        if (CollectionUtil.isNotEmpty(allToolDemandPredictionVoList))
            allToolDemandPredictionVoList = allToolDemandPredictionVoList.stream().sorted(Comparator.comparing(ToolDemandPredictionVo::getToolCode,Comparator.nullsFirst(String::compareTo))).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(allToolDemandPredictionVoList)){
            allToolDemandPredictionVoList.forEach(toolDemandPredictionVo -> {
                ToolDemandForecastReportToolEntity toolDemandForecastReportToolEntity = new ToolDemandForecastReportToolEntity();

                try {
                    if (StringUtils.isNotEmpty(stringListMap.get(toolDemandPredictionVo.getToolCode()).get(0).getLife())){

                        String life  = stringListMap.get(toolDemandPredictionVo.getToolCode()).get(0).getLife();
                        toolDemandForecastReportToolEntity.setLife(life.substring(0, life.length()-1));
//                    double lifeDouble = Double.parseDouble(life.substring(0, life.length()-1));
//                    BigDecimal s = toolDemandPredictionVo.getSingleTime();
                    }else {
                        toolDemandForecastReportToolEntity.setLife("200");
                    }
                }catch (NullPointerException e){
                    toolDemandForecastReportToolEntity.setLife("200");
                }
                BigDecimal decimal3 = new BigDecimal(toolScheduleService.getDefaultLife(toolDemandPredictionVo.getToolCode()));
                BigDecimal result = toolDemandPredictionVo.getSingleTime().divide(decimal3 , BigDecimal.ROUND_CEILING);

//                try {
                    if (CollectionUtil.isNotEmpty(listMap.get(toolDemandPredictionVo.getToolModel())))
                    doubleList.add(listMap.get(toolDemandPredictionVo.getToolModel()).get(0).getPrice()*result.doubleValue());
//                }catch (Exception e){}
                bigDecimalList.add(toolDemandPredictionVo.getSingleTime());
            });
        }
        if (CollectionUtil.isNotEmpty(allToolDemandPredictionVoList)){
            //Double a =  doubleList.stream().mapToDouble(Double::doubleValue).sum();
            toolDemandForecastReportProductEntity
                    .setSumPrice(toolDemandForecastReportToolEntityList
                            .stream()
                            .filter(toolDemandForecastReportToolEntity -> ObjectUtil.isNotNull(toolDemandForecastReportToolEntity.getPrice()))
                            .mapToDouble(ToolDemandForecastReportToolEntity::getPrice).sum());
        }
        BigDecimal decimal = bigDecimalList.stream().filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        toolDemandForecastReportProductEntity.setSumTime(decimal);
        toolDemandForecastReportProductEntity.setMachine(machineList.toString().substring(1,machineList.toString().length()-1));
        if (Objects.nonNull(decimal)){
            BigDecimal decimal1 = new BigDecimal(orderEntityList.get(0).getPlanNumber());
            BigDecimal result = decimal.divide(decimal1 , 2 , BigDecimal.ROUND_HALF_UP);
            toolDemandForecastReportProductEntity.setTime(result);
        };
        List<ToolDemandForecastReportToolEntity> pageList = new ArrayList<>();
        map1.put("productList",toolDemandForecastReportProductEntity);
        if(CollectionUtil.isNotEmpty(toolDemandForecastReportToolEntityList)){
            pageList = CommonUtil.pageList(toolDemandForecastReportToolEntityList , assemblyRetrievalReq.getPageNo() , assemblyRetrievalReq.getPageSize());
        }
        map1.put("toolList",toolDemandForecastReportToolEntityList);
        map1.put("total",map.get("total"));
        return map1;
    }
    public static <T> List<T> changeList(Object object,Class<T> clazz){
        try {
            List<T> result = new ArrayList<>();
            if (object instanceof List<?>){
                for (Object o : (List<?>) object) {
                    String string = JSONObject.toJSONString(o);
                    T t = JSONObject.parseObject(string, clazz);
                    result.add(t);
                }
                return result;
            }
            return null;
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
        }

        return null;
    }

    public void exportToolDemandForecastReport(HttpServletResponse response, OrderForecastReportExport orderForecastReportExport) throws ToolScheduleException {
        String taskId = orderForecastReportExport.getToolDemandForecastReportProductEntity().getTaskId();
        String outputFileName = taskId.trim() + "需求预测报表";
        //OrderForecastReportExport orderForecastReportExport = buildToolDemandForecastReport(taskId);

        //获取模板
        ClassPathResource classPathResource = new ClassPathResource("/template/需求预测报表模板.xlsx");
        //输入流
        InputStream inputStream = null;

        //输出流
        ServletOutputStream outputStream = null;

        //Excel对象
        ExcelWriter excelWriter = null;
        try {
            //输入流
            inputStream = classPathResource.getInputStream();
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(outputFileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            outputStream = response.getOutputStream();

            // InputStream templateStream = getClass().getClassLoader().getResourceAsStream(CommonConstant.Tool_DEMAND_TEMPLATE_PATH);
            excelWriter = EasyExcel.write(response.getOutputStream())
                    .autoCloseStream(Boolean.TRUE)
                    .withTemplate(inputStream).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            // 列表
            excelWriter.fill(orderForecastReportExport.getToolForecastReportToolExportList(), fillConfig, writeSheet);

            excelWriter.fill(orderForecastReportExport.getToolDemandForecastReportProductEntity(), writeSheet);

            // 结束写入
            excelWriter.finish();

        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            log.error("export order detail failed=====>", e);
        } finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
            //关闭流
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private OrderForecastReportExport buildToolDemandForecastReport(String taskId) throws ToolScheduleException {
        AssemblyRetrievalReq assemblyRetrievalReq = new AssemblyRetrievalReq();
        assemblyRetrievalReq.setPageNo(1);
        assemblyRetrievalReq.setPageSize(200);
        assemblyRetrievalReq.setTaskId(taskId);
        Map<String, Object> paramMap = queryToolDemandForecastReport(assemblyRetrievalReq);
        OrderForecastReportExport orderForecastReportExport = new OrderForecastReportExport();
        orderForecastReportExport.setToolDemandForecastReportProductEntity((ToolDemandForecastReportProductEntity) paramMap.get("productList"));
        orderForecastReportExport.setToolForecastReportToolExportList((List<ToolDemandForecastReportToolEntity>) paramMap.get("toolList"));
        return orderForecastReportExport;
    }

    public void exportToolUsageReport(HttpServletResponse response, ToolUsageReportExport toolUsageReportExport) throws ToolScheduleException {
        String taskId = toolUsageReportExport.getOrderEntity().getTaskId();
        String outputFileName = taskId.trim() + "实际消耗报表模板.xlsx";
        //ToolUsageReportExport toolUsageReportExport = buildToolUsageReport(taskId);
        CommonUtil.exportExcelFile(toolUsageReportExport , "/template/实际消耗报表模板.xlsx" , response , outputFileName);
//        //获取模板
//        ClassPathResource classPathResource = new ClassPathResource("/template/实际消耗报表模板.xlsx");
//        //输入流
//        InputStream inputStream = null;
//
//        //输出流
//        ServletOutputStream outputStream = null;
//
//        //Excel对象
//        ExcelWriter excelWriter = null;
//        try {
//            //输入流
//            inputStream = classPathResource.getInputStream();
//            response.setContentType("application/vnd.ms-excel");
//            response.setCharacterEncoding("utf-8");
//            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
//            String fileName = URLEncoder.encode(outputFileName, "UTF-8");
//            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//            outputStream = response.getOutputStream();
//
//            // InputStream templateStream = getClass().getClassLoader().getResourceAsStream(CommonConstant.Tool_DEMAND_TEMPLATE_PATH);
//            excelWriter = EasyExcel.write(response.getOutputStream())
//                    .autoCloseStream(Boolean.TRUE)
//                    .withTemplate(inputStream).build();
//            WriteSheet writeSheet = EasyExcel.writerSheet().build();
//            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
//            // 列表
//            excelWriter.fill(toolUsageReportExport.getOrderEntity(), fillConfig, writeSheet);
//
//            excelWriter.fill(toolUsageReportExport.getToolReportVos(), writeSheet);
//
//            // 结束写入
//            excelWriter.finish();
//
//        } catch (UnsupportedEncodingException e) {
//            throw new RuntimeException(e);
//        } catch (Exception e) {
//            log.error("export order detail failed=====>", e);
//        } finally {
//            if (excelWriter != null) {
//                excelWriter.finish();
//            }
//            //关闭流
//            if (outputStream != null) {
//                try {
//                    outputStream.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//            if (inputStream != null) {
//                try {
//                    inputStream.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }
    }

    private ToolUsageReportExport buildToolUsageReport(String taskId) throws ToolScheduleException {
        ToolUsageReportReq toolUsageReportReq = new ToolUsageReportReq();
        toolUsageReportReq.setPageNum(1);
        toolUsageReportReq.setPageSize(200);
        toolUsageReportReq.setTaskId(taskId);
        toolLieService.toolUsageReport(toolUsageReportReq);
        return null;
    }
}
